package controller;

import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import model.AuctionBean;
import model.AuctionDAO;
import model.BidDAO;
import model.SignDao;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**
 * Servlet implementation class AuctionServlet
 */
public class AuctionServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	DBmanager dbm = null;
	SignDao sDAO;
	AuctionDAO aDAO;
	BidDAO bDAO;
	File f;
	Calendar now;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public AuctionServlet() {
        super();
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		initialize();
		HttpSession session = request.getSession();
		if(session.getAttribute("userid") != null){
			session.invalidate();
		}
		response.sendRedirect("index.jsp");
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		initialize();
		now = Calendar.getInstance();
		/*
		 * possible actions on POST:
		 * -register
		 * -loggin in
		 * -add auction
		 * -delete auction
		 * -place bid
		 * 
		 * strategy: do a switch on either a hidden field or the button name/value
		 */
		HttpSession session = request.getSession();
		String action = request.getParameter("button");
		if(action == null){
			String title = "", details = "", price = "", dend = "", owner = "", filename = "";
			DiskFileItemFactory dfi = new DiskFileItemFactory();
			dfi.setRepository(f);

			ServletFileUpload sfu = new ServletFileUpload(dfi);
			try{
				@SuppressWarnings("rawtypes")
				List item = sfu.parseRequest(request);
				@SuppressWarnings("rawtypes")
				Iterator itr = item.iterator();
				
				while(itr.hasNext()){
					try{
						FileItem fi = (FileItem)itr.next();
						if(fi.getFieldName().equals("title")) title = fi.getString();
						if(fi.getFieldName().equals("details")) details = fi.getString();
						details = details.replaceAll("\n", "<br>");
						if(fi.getFieldName().equals("price")) price = fi.getString();
						if(fi.getFieldName().equals("dend")) dend = fi.getString();
						if(fi.getFieldName().equals("owner")) owner = fi.getString();
						if(!fi.isFormField()){
							filename = fi.getName();
							int i = 1;
							filename = i + filename.substring(filename.length()-4);
							File file = new File(f,filename);
							while(file.exists()){
								i++;
								filename = i + filename.substring(filename.length()-4);
								file = new File(f,filename);
							}
							fi.write(file);
							createThumb(file);
						}
					}catch(FileUploadException ex){
						ex.printStackTrace();
						continue;
					}
				}
			}catch(Exception ex){
				ex.printStackTrace();
			}
			if(title.equals("") || filename.equals("") || details.equals("")){
				response.sendRedirect("wrongAuction.html");
				return;
			}
			try{
				long l = now.getTimeInMillis()+(Integer.parseInt(dend)*86400000);
				aDAO.newAuction(title, filename, details, Integer.parseInt(owner), Double.parseDouble(price), new Timestamp(l));
				response.sendRedirect("index.jsp");
			}catch(Exception e){
				response.sendRedirect("wrongAuction.html");
				e.printStackTrace();
				return;
			}
			
		}
		else if(action.equalsIgnoreCase("sign in")){
			String username = request.getParameter("Email");
			String password = request.getParameter("Passwd");
			int i = sDAO.checkUser(username, hashPassword(password));
			if(i > 0){
				session.setAttribute("userid", i);
				session.setAttribute("username", username);
				response.sendRedirect("index.jsp");
			}else{
				response.sendRedirect("wrongLogin.html");
			}
		}
		else if(action.equalsIgnoreCase("sign up")){
			String username = request.getParameter("Email");
			String password = request.getParameter("Passwd");
			String passwd2 = request.getParameter("Passwd2");
			if(username.equals("") || password.equals("")){
				response.sendRedirect("wrongRegister.html");
			}
			if(!password.equals(passwd2)){
				response.sendRedirect("wrongRegister.html");
			}else{
				sDAO.newUser(username, hashPassword(password));
				response.sendRedirect("index.jsp");
			}
		}
		else if(action.equalsIgnoreCase("add auction")){
			//this doesnt work since the form is of a different type, see if(action == null)
		}
		else if(action.equalsIgnoreCase("delete auction")){
			int aid = Integer.parseInt(request.getParameter("auctionid"));
			if(aid!=0){
				ArrayList<AuctionBean> list = aDAO.getBeans();
				for(AuctionBean bean: list){
					if(bean.getID() == aid){
						String pic = bean.getPic();
						String imgpath = getServletContext().getRealPath("\\filepathInContext");
						imgpath = imgpath.substring(0, imgpath.lastIndexOf("\\")+1) + "img\\";
						File picFile = new File(imgpath + pic);
						picFile.delete();
						picFile = new File(imgpath + "thumbs\\" + pic);
						picFile.delete();
					}
				}
				aDAO.deleteAuction(aid);
				bDAO.deleteBids(aid);
			}
			response.sendRedirect("index.jsp");
		}
		else if(action.equalsIgnoreCase("place bid")){
			if(session.getAttribute("userid") != null){
				int bidder = new Integer("" + session.getAttribute("userid"));
				int auction = new Integer(request.getParameter("auction"));
				double bid = 0;
				try{
					double x = new Double(request.getParameter("bid"));
					String s = String.format("%.2f", x).replace(',', '.');
					bid = new Double(s);
				}catch(NumberFormatException e){
					response.sendRedirect("invalidBid.html");
					return;
				}
				double startprice = 0;
				for(AuctionBean b: aDAO.getBeans()){
					if(b.getID() == auction){
						startprice = b.getPrice();
						//check whether the auction is already over
						if(b.getEnd().getTime() < now.getTimeInMillis()){
							response.sendRedirect("invalidBid.html");
							return;
						}
					}
				}
				
				if(bid > bDAO.getMaxBid(auction) && bid > startprice){
					bDAO.newBid(auction, bidder, bid, new Timestamp(now.getTimeInMillis()));
				}else{
					//bid is lager of gelijk
					response.sendRedirect("invalidBid.html");
					return;
				}
			}
			response.sendRedirect("index.jsp");
		}
		
	}
	
	private void initialize(){
		if(dbm == null){
			dbm = DBmanager.getInstance(getServletContext());
	        sDAO = new SignDao();
	        aDAO = new AuctionDAO();
	        bDAO = new BidDAO();
	        String imgpath = getServletContext().getRealPath("img");
			f = new File(imgpath);
		}
	}
	
	private String hashPassword(String password) {
		String hashword = null;
			try {
				MessageDigest md5 = MessageDigest.getInstance("MD5");
				md5.update(password.getBytes());
				BigInteger hash = new BigInteger(1, md5.digest());
				hashword = hash.toString(16);
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
			}
		return hashword;
	}
	
	private void createThumb(File f){
		BufferedImage originalImage = null;
		try{
			originalImage = ImageIO.read(f);
			double IMGW = originalImage.getWidth();
			double IMGH = originalImage.getHeight();
			double scale = 1;
			if(IMGW >= IMGH){
				scale = 1.0/(IMGW/100);
				IMGW = 100;
				IMGH = (int)Math.round(IMGH*scale);
			}else{
				scale = 1.0/(IMGH/100);
				IMGH = 100;
				IMGW = (int)Math.round(IMGW*scale);
			}
			BufferedImage resizedImage = new BufferedImage((int)IMGW, (int)IMGH, BufferedImage.TYPE_INT_RGB);
			Graphics2D g = resizedImage.createGraphics();
			g.setComposite(AlphaComposite.Src);
			g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
			g.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
			g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
			g.drawImage(originalImage, 0, 0, (int)IMGW, (int)IMGH, null);
			g.dispose();
			String path = f.getAbsolutePath();
			File thumb = new File(path.substring(0, path.lastIndexOf(File.separatorChar)) + File.separatorChar + "thumbs" + File.separatorChar + f.getName());
			thumb.mkdirs();
			thumb.createNewFile();
			ImageIO.write(resizedImage, thumb.getName().substring(thumb.getName().indexOf(".")+1), thumb);
		}catch(IOException e){
			e.printStackTrace();
		}
	}
}
